<?php

class VerificationCode
{
    private $width;//验证码宽度
    private $height;//验证码高度
    private $codeNum;//验证码中的字符数
    private $type;//验证码中字符类型
    private $dotNum;//验证码干扰雪花数目
    private $lineNum;//验证码干扰线条数目
    private $image;//验证码图片
    private $chars;//验证码字符串

    /**
     * securityCode构造方法
     * @param array $params
     * @param $sessionKey
     */
    function __construct($params = [])
    {
        //给当前类中拥有的部分成员属性赋值
        $keys = array_keys(get_class_vars(__CLASS__));
        foreach ($params as $key => $value) {
            if (in_array($key, $keys)) {
                $this->$key = $params[$key];
            }
        }
    }

    //生成验证码图像
    public function getImage($sessionKey)
    {
        //创建图像
        $this->image = $this->createImage();
        //生成随机验证码字符
        $this->chars = $this->createChar();
        //绘制验证码
        $this->drawCode();
        //绘制干扰点
        $this->interferenceDots();
        //绘制干扰线条
        $this->interferenceLines();
        //显示图片
        header("Content-type:image/png");
        imagepng($this->image);
        //释放与image关联的内存
        imagedestroy($this->image);
        //启动session，并将验证码字符串存到session中
        session_start();
        $_SESSION[$sessionKey] = $this->chars;
    }

    //创建图像
    private function createImage()
    {
        //默认黑色图像
        $image = imagecreatetruecolor($this->width, $this->height);
        //生成背景色
        $color = imagecolorallocate($image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255));
        //填充背景色
        imagefill($image, 0, 0, $color);
        return $image;
    }

    //生成验证码字符，1代表只有数字，2代表只有字母，3代表字母加数字
    private function createChar()
    {
        if ($this->type == 1) {
            //implode将数组元素组合为一个字符串
            $chars = implode("", range(0, 9));//生成数字
        } else if ($this->type == 2) {
            $chars = implode("", range("A", "Z"));//生成字母
        } elseif ($this->type == 3) {
            $chars = implode("", array_merge(range(0, 9), range("A", "Z")));//生成数字字母
        }
        $chars = str_shuffle($chars);//打乱字符串排序
        if ($this->codeNum > strlen($chars)) {
            exit("验证码位数必须小于" . strlen($chars));//判断验证码位数是不是超过字符串长度
        }
        $chars = substr($chars, 0, $this->codeNum);//截取字符
        return $chars;
    }

    //绘制验证码
    public function drawCode()
    {
        $font_file = __DIR__ . "\ARIALNI.TTF";
        //绘制每个字符
        for ($i = 0; $i < $this->codeNum; $i++) {
            $color = imagecolorallocate($this->image, mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200));
            $x = mt_rand(1, 5) + $this->width / 4 * $i;
            $y = mt_rand(1, 5) + $this->height * 2 / 3;
            imagettftext($this->image, 20, 0, $x, $y, $color, $font_file, $this->chars[$i]);
        }
    }

    //绘制干扰圆点
    private function interferenceDots()
    {
        for ($i = 0; $i < $this->dotNum; $i++) {
            $color = imagecolorallocate($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            //随机绘制一个像素点
            imagesetpixel($this->image, mt_rand(0, $this->width - 1), mt_rand(0, $this->height - 1), $color);
        }
    }

    //绘制干扰线条
    private function interferenceLines()
    {
        //绘制干扰线条
        for ($i = 0; $i < $this->lineNum; $i++) {
            $color = imagecolorallocate($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            //绘制一条随机线段
            imageline($this->image, mt_rand(0, $this->width - 1), mt_rand(0, $this->height - 1), mt_rand(0, $this->width - 1), mt_rand(0, $this->height - 1), $color);
        }
    }
}

